package z.explorer.ui.common;

import javax.swing.table.DefaultTableModel;
import z.explorer.core.storage.*;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.util.*;

public class ZTableModel extends DefaultTableModel {

	private static final long serialVersionUID = 2200139047480859656L;

	private List data = null;

	private ArrayList<PropMap> columns = null;

	public ZTableModel() {
		super();
	}

	/* generic constructor */

	public ZTableModel(List list) {
		loadData(list);
	}

	private void loadData(List list) {
		data = list;
		if (data == null || data.size() == 0)
			return;
		Object obj = list.get(0);
		initColumn();
	}

	public void reloadData(List list) {
		loadData(list);
		fireTableStructureChanged();
	}

	public void initColumn() {
		columns = new ArrayList<PropMap>();
		if (data == null || data.size() == 0)
			return;
		try {
			BeanInfo beanInfo;
			Object obj = data.get(0);
			beanInfo = Introspector.getBeanInfo(obj.getClass(), obj.getClass()
					.getSuperclass());

			PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor pd : pds) {
				PropMap pm = new PropMap();
				pm.name = pd.getName();
				pm.getter = pd.getReadMethod();
				pm.setter = pd.getWriteMethod();
				if (pd.getPropertyType().isPrimitive()) {
					pm.type = pm.getter.invoke(obj, (Object[]) null).getClass();
				} else {
					pm.type = pd.getPropertyType();
				}
				columns.add(pm);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

	@Override
	public int getColumnCount() {
		// TODO Auto-generated method stub
		if (columns == null)
			return 0;
		else
			return columns.size();
	}

	@Override
	public String getColumnName(int column) {
		// TODO Auto-generated method stub
		if (columns == null)
			return null;
		else
			return columns.get(column).toString();
	}

	@Override
	public Class getColumnClass(int columnIndex) {
		// TODO Auto-generated method stub
		return columns.get(columnIndex).type;
		// return String.class;
	}

	@Override
	public int getRowCount() {
		// TODO Auto-generated method stub
		if (data == null)
			return 0;
		return data.size();
	}

	@Override
	public Object getValueAt(int row, int column) {
		// TODO Auto-generated method stub

		try {

			PropMap pm = columns.get(column);
			Method method = pm.getter;
			return method.invoke(data.get(row), null);

		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	@Override
	public void setValueAt(Object aValue, int row, int column) {
		// TODO Auto-generated method stub
		try {
			columns.get(column).setter.invoke(data.get(row), aValue);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public int getIndexByName(String name){
		for(int i=0;i<columns.size();i++)
		{
			if (columns.get(i).name.equals(name))
				return i;
		}
		return -1;
	}
	private class PropMap {
		public String name;
		public Method getter;
		public Method setter;
		public Class type;

		public String toString() {
			return name;
		}
	}

}
